From 0fe8bb487c1fc7b73eb0ef39c123a0a544e27835 Mon Sep 17 00:00:00 2001 From: robertl Date: Sun, 15 Sep 2002 23:05:56 +0000 Subject: [PATCH] A slew of updates from Alex Mottram. Thanx! --- gpsbabel/README | 7 +++ gpsbabel/mxf.c | 91 ++++++++++++----------------- gpsbabel/psp.c | 150 ++++++++++++++++++++++++------------------------ gpsbabel/testo | 8 +++ 4 files changed, 125 insertions(+), 131 deletions(-) diff --git a/gpsbabel/README b/gpsbabel/README index 194820d67..67801c46f 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -99,6 +99,7 @@ THE FORMATS write them. PSP + Microsoft's PocketStreets 2002 Pushpin (.PSP) format is not yet completely documented. THE .PSP MODULE DOES NOT WORK WITH MS STREETS & TRIPS 2002 .EST FILES. To create .PSP files from @@ -114,6 +115,12 @@ THE FORMATS .MPS files. Unfortunately, you need one .PSP file for every .MPS file. :( + MXF + + Maptech Exchange Format - Another CSV format file. This format + complies with (at least) Maptech Terrain Navigator, Terrain + Professional, Take a Hike, and ExpertGPS import/export MFX. + Maptech MXF Maptech's MXF is a CSV on steroids. Contributed by Alex Mottram. diff --git a/gpsbabel/mxf.c b/gpsbabel/mxf.c index e360efebc..aa13f1f19 100644 --- a/gpsbabel/mxf.c +++ b/gpsbabel/mxf.c @@ -1,14 +1,14 @@ /* Mapsend Exchange Format (.mxf) (Maptech Terrain Navigator, Terrain Professional, Take a Hike) - (Aka Yet Another CSV Format) + (AKA Yet Another CSV Format) - Contributed to gpsbabel by Alex Mottram + Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com) - LAT,LON,"WPT Name", "Big Name","Small Name",COLORxFF,(int)ICON + LAT, LON, "Waypoint Name", "Big Name", "Small Name", COLOR, ICON - as described at: www.memory-map.co.uk/downloads/PDF/mm_tsb3_import_export_text_files.pdf - tested against ExpertGPS import/export .mxf files. + As described in Maptech Terrain Navigator Help File. + Tested against Terrain Navigator and ExpertGPS import/export .MXF files. Copyright (C) 2002 Robert Lipe, robertlipe@usa.net @@ -36,9 +36,8 @@ static FILE *file_in; static FILE *file_out; -/* remember what dave & gamera say about pointer math... */ static char * -cvsstringclean(char * string) +csvstringclean(char * string) { static char * p1 = NULL; char * p2 = NULL; @@ -73,7 +72,8 @@ cvsstringclean(char * string) return (p1); } -/* string parser. sorta like strtok with quotes & pointers.. */ +/* string parser. sorta like strtok with quotes & pointers.. */ +/* designed to handle quoted and delimited data within quotes. */ static char * csvparse(char *stringstart, char *delimiter) { @@ -82,6 +82,7 @@ csvparse(char *stringstart, char *delimiter) static char *tmp = NULL; size_t dlen; int quotedepth = 0; + short int dfound; if (!p) { p = stringstart; @@ -99,8 +100,9 @@ csvparse(char *stringstart, char *delimiter) sp = p; dlen = strlen(delimiter); + dfound = 0; - while ((*p) && (! tmp)) { + while ((*p) && (! dfound)) { if (*p == '"') { if (quotedepth) quotedepth--; @@ -109,32 +111,31 @@ csvparse(char *stringstart, char *delimiter) } if ((!quotedepth) && (strncmp(p, delimiter, dlen) == 0)) { - tmp = (char *) calloc((p - sp) + 1, sizeof(char)); - if (! tmp) { - fatal(MYNAME ": cannot allocate memory\n"); - } - strncpy(tmp, sp, (p - sp)); + dfound = 1; + + } else { + p++; } - p++; - } - - if (!tmp) { - tmp = (char *) calloc((p - sp) + 1, sizeof(char)); - if (! tmp) { - fatal(MYNAME ": cannot allocate memory\n"); - } + } - strncpy(tmp, sp, (p - sp)); + tmp = (char *) calloc((p - sp) + 1, sizeof(char)); - p = NULL; + if (! tmp) { + fatal(MYNAME ": cannot allocate memory\n"); } - if (tmp) { - return (tmp); + strncpy(tmp, sp, (p - sp)); + + if (dfound) { + /* skip over the delimiter */ + p += dlen; + } else { + /* end of the line */ + p = NULL; } - return (NULL); + return (tmp); } static void @@ -190,7 +191,7 @@ data_read(void) } s = buff; - s = csvparse(s, ","); + s = csvparse(s, ", "); i = 0; while (s) { @@ -202,10 +203,10 @@ data_read(void) wpt_tmp->position.longitude.degrees = atof(s); break; case 2: - wpt_tmp->description = strdup(cvsstringclean(s)); + wpt_tmp->description = strdup(csvstringclean(s)); break; case 3: - wpt_tmp->shortname = strdup(cvsstringclean(s)); + wpt_tmp->shortname = strdup(csvstringclean(s)); break; case 4: /* ignore. another name-type */ @@ -218,27 +219,25 @@ data_read(void) break; default: /* whoa! nelly */ - printf ("%s: Warning: data fields on line %d exceed specification.\n", + fprintf (stderr, "%s: Warning: data fields on line %d exceed specification.\n", MYNAME, linecount); break; } i++; - s = csvparse(NULL, ","); + s = csvparse(NULL, ", "); } if (i != 7) { free(wpt_tmp); - printf ("%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n", + fprintf (stderr, "%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n", MYNAME, i, linecount); } else { waypt_add(wpt_tmp); } } else { - /* this complains too much - * printf ("%s: WARNING - blank line at line %d.\n", MYNAME, linecount); - */ + /* empty line */ } } while (!feof(file_in)); @@ -247,18 +246,13 @@ data_read(void) static void mxf_disp(waypoint * wpt) { - double lon, lat; int icon = 47; /* default to "dot" */ const char *color_hex = "ff0000"; - lon = wpt->position.longitude.degrees; - lat = wpt->position.latitude.degrees; - fprintf(file_out, "%08.5f, %08.5f, \"%s\", \"%s\", \"%s\", %s, %d\n", - lat, lon, + wpt->position.latitude.degrees, wpt->position.longitude.degrees, wpt->description, wpt->shortname, wpt->description, color_hex, icon); - } static void @@ -267,7 +261,6 @@ data_write(void) waypt_disp_all(mxf_disp); } - ff_vecs_t mxf_vecs = { rd_init, wr_init, @@ -277,15 +270,3 @@ ff_vecs_t mxf_vecs = { data_write, }; - -/* - Excerpt from Maptech help file. - - Below is an example of the .MXF file format: - - 43.7601389, -071.2791299, "Cottonwood", "Cttnwd", "A very large tree", 800080, 137 - 43.7617236, -071.2917695, "Fencepost", "Fncpst", "", 808080, 14 - 43.7576237, -071.2888850, "Aspen", "Aspen", "", ffff, 137 - 43.7562457, -071.2777147, "Cache", "Cache", "", ff, 138 - 43.7576583, -071.2701399, "Tent site", "Tntst", "", ff, 111 -*/ diff --git a/gpsbabel/psp.c b/gpsbabel/psp.c index c8a8f38fe..18fd32a4d 100644 --- a/gpsbabel/psp.c +++ b/gpsbabel/psp.c @@ -1,6 +1,6 @@ /* PocketStreets 2002 Pushpin Files - Contributed to gpsbabel by Alex Mottram. + Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com) Copyright (C) 2002 Robert Lipe, robertlipe@usa.net @@ -21,39 +21,56 @@ */ #include "defs.h" - #include #include /* for M_PI */ -#define MYNAME "PSP" +#define MYNAME "PSP" -/*#define _DEBUG_PSP 1*/ #define MAXPSPSTRINGSIZE 256 #define MAXPSPOUTPUTPINS 8192 /* Any more points than this is ludicrous */ static FILE *psp_file_in; static FILE *psp_file_out; -#ifdef _DEBUG_PSP -static void -dump_bufferstuff(char * header, char * buffer, int bufferlen) -{ - int i; +static int +psp_fread(void *buff, size_t size, size_t members, FILE * fp) { + size_t br; - printf("%s\n--------\n", header); + br = fread(buff, size, members, fp); + + if (br != members) { + fatal(MYNAME ": requested to read %d bytes, read %d bytes.\n", members, br); + } - for (i = 0 ; i < bufferlen ; i++) { - printf("%0.2X ", (unsigned char)buffer[i]); - } - printf("\n"); + return (br); +} + +static int +valid_psp_header(char * header, int len) { + char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x00 }; /* 1niP */ + char *p, *s; + + if (len != 32) { + return (-1); + } + + p = header_bytes; + s = header; + + while (*p) { + if (*p++ != *s++) { + return(-1); + } + } + + return (0); } -#endif static char * buffer_washer(char * buff, int buffer_len) { int i; - + for (i = 0 ; i < buffer_len - 1; i++) { if (buff[i] == '\0') { memcpy(&buff[i], &buff[i+1], buffer_len - i); @@ -68,7 +85,7 @@ buffer_washer(char * buff, int buffer_len) static void psp_rd_init(const char *fname) { - psp_file_in = fopen(fname, "r"); + psp_file_in = fopen(fname, "rb"); if (psp_file_in == NULL) { fatal(MYNAME ": Cannot open %s for reading\n", fname); } @@ -83,7 +100,7 @@ psp_rd_deinit(void) static void psp_wr_init(const char *fname) { - psp_file_out = fopen(fname, "w"); + psp_file_out = fopen(fname, "wb"); if (psp_file_out == NULL) { fatal(MYNAME ": Cannot open %s for writing\n", fname); } @@ -98,17 +115,21 @@ psp_wr_deinit(void) static void psp_read(void) { - char buff[MAXPSPSTRINGSIZE + 1]; + char buff[MAXPSPSTRINGSIZE + 1]; double radians; waypoint *wpt_tmp; int stringsize; short int pincount; /* 32 bytes - file header */ - fread(&buff[0], 1, 32, psp_file_in); - + psp_fread(&buff[0], 1, 32, psp_file_in); + + if (valid_psp_header(buff, 32) != 0) { + fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n"); + } + pincount = *(short int *)&buff[12]; - + while (pincount--) { wpt_tmp = calloc(sizeof(*wpt_tmp),1); @@ -119,68 +140,64 @@ psp_read(void) /* things we will probably never know about this waypoint */ /* coming from a pushpin file. */ - /* + /* wpt_tmp->creation_time; wpt_tmp->position.altitude.altitude_meters; wpt_tmp->url; wpt_tmp->url_link_text; wpt_tmp->icon_descr; TODO: map this. */ - + /* 4 bytes at start of record */ /* coming out of S&T, this 1st byte is probably the pin # (0x01, 0x02, etc...) */ /* coming from pocketstreets, it's generally 0x00. Sometimes 0xC3. ? */ - - fread(&buff[0], 1, 4, psp_file_in); + + psp_fread(&buff[0], 1, 4, psp_file_in); /* 1 byte, unkown */ - fread(&buff[0], 1, 1, psp_file_in); + psp_fread(&buff[0], 1, 1, psp_file_in); /* 8 bytes - latitude in radians */ - fread(&buff[0], 1, 8, psp_file_in); + psp_fread(&buff[0], 1, 8, psp_file_in); radians = *(double *)&buff[0]; wpt_tmp->position.latitude.degrees = (radians * 180.0) / M_PI; /* 8 bytes - longitude in radians */ - fread(&buff[0], 1, 8, psp_file_in); + psp_fread(&buff[0], 1, 8, psp_file_in); radians = *(double *)&buff[0]; wpt_tmp->position.longitude.degrees = (radians * 180.0) / M_PI; /* 1 byte - pin display properties */ - fread(&buff[0], 1, 1, psp_file_in); + psp_fread(&buff[0], 1, 1, psp_file_in); /* 3 bytes - unknown */ - fread(&buff[0], 1, 3, psp_file_in); + psp_fread(&buff[0], 1, 3, psp_file_in); - /* 1 bytes - icon 0x00 - 0x27 */ - fread(&buff[0], 1, 1, psp_file_in); + /* 1 bytes - icon 0x00 - 0x27 */ + psp_fread(&buff[0], 1, 1, psp_file_in); /* 3 bytes - unknown */ - fread(&buff[0], 1, 3, psp_file_in); + psp_fread(&buff[0], 1, 3, psp_file_in); /* 1 byte - string size */ - fread(&buff[0], 1, 1, psp_file_in); + psp_fread(&buff[0], 1, 1, psp_file_in); stringsize = buff[0]; stringsize *= 2; - + if (stringsize > MAXPSPSTRINGSIZE) { fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE); } /* stringsize bytes - string data */ - fread(&buff[0], 1, stringsize, psp_file_in); + psp_fread(&buff[0], 1, stringsize, psp_file_in); buffer_washer(buff, stringsize); -#ifdef _DEBUG_PSP - printf ("string1: [%s]\n", buff); -#endif - wpt_tmp->shortname = strdup(buff); /* 1 bytes string size */ - fread(&buff[0], 1, 1, psp_file_in); + psp_fread(&buff[0], 1, 1, psp_file_in); stringsize = buff[0]; stringsize *= 2; @@ -189,22 +206,15 @@ psp_read(void) fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE); } -#ifdef _DEBUG_PSP - printf ("string2: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in)); -#endif - - /* stringsize bytes - string data */ - fread(&buff[0], 1, stringsize, psp_file_in); + /* stringsize bytes - string data */ + psp_fread(&buff[0], 1, stringsize, psp_file_in); buffer_washer(buff, stringsize); -#ifdef _DEBUG_PSP - printf ("string2: [%s]\n", buff); -#endif wpt_tmp->description = strdup(buff); /* 1 bytes - string size */ - fread(&buff[0], 1, 1, psp_file_in); + psp_fread(&buff[0], 1, 1, psp_file_in); stringsize = buff[0]; stringsize *= 2; @@ -213,24 +223,13 @@ psp_read(void) fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE); } - -#ifdef _DEBUG_PSP - printf ("string: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in)); -#endif - /* stringsize bytes - string data (address?) */ - fread(&buff[0], 1, stringsize, psp_file_in); + psp_fread(&buff[0], 1, stringsize, psp_file_in); buffer_washer(buff, stringsize); -#ifdef _DEBUG_PSP - printf ("string3: [%s]\n", buff); -#endif - - waypt_add(wpt_tmp); - } - - + waypt_add(wpt_tmp); + } } static void @@ -248,11 +247,11 @@ psp_disp(waypoint *wpt) /* 4 leading bytes */ memset(&tbuf, '\0', sizeof(tbuf)); fwrite(&tbuf, 1, 4, psp_file_out); - + /* my test files seem to always have this byte as 0x03, */ /* although nothing seems to really care. */ c = 0x03; - + /* 1 unknown bytes */ fwrite(&c, 1, 1, psp_file_out); @@ -263,13 +262,13 @@ psp_disp(waypoint *wpt) fwrite(&lon, 1, 8, psp_file_out); /* 1 byte - pin properties */ - c = 0x14; /* display pin on! display notes on! */ + c = 0x14; /* display pin name on! display notes on! */ fwrite(&c, 1, 1, psp_file_out); memset(&tbuf, '\0', sizeof(tbuf)); /* 3 unknown bytes */ - fwrite(&tbuf, 1, 3, psp_file_out); + fwrite(&tbuf, 1, 3, psp_file_out); /* 1 icon byte 0x00 = PIN */ fwrite(&tbuf, 1, 1, psp_file_out); @@ -279,7 +278,7 @@ psp_disp(waypoint *wpt) c = strlen(wpt->shortname); /* 1 string size */ - fwrite(&c, 1, 1, psp_file_out); + fwrite(&c, 1, 1, psp_file_out); for (i = 0 ; wpt->shortname[i] ; i++) { fwrite(&wpt->shortname[i], 1, 1, psp_file_out); /* char */ @@ -298,13 +297,12 @@ psp_disp(waypoint *wpt) /* just for the hell of it, we'll scrap the third string. */ c = strlen(tbuf); /* 1 byte string size */ - fwrite(&c, 1, 1, psp_file_out); + fwrite(&c, 1, 1, psp_file_out); for (i = 0 ; tbuf[i] ; i++) { fwrite(&tbuf[i], 1, 1, psp_file_out); /* char */ fwrite(&tbuf[0], 1, 1, psp_file_out); /* null */ } - } static void @@ -318,16 +316,16 @@ psp_write(void) /* offset 0x0C - 0x0D = 2 byte pin count */ s = waypt_count(); - + if (s > MAXPSPOUTPUTPINS) { - fatal(MYNAME ": output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS); + fatal(MYNAME ": attempt to output too many pushpins (%d). The max is %d. Sorry.\n", s, MAXPSPOUTPUTPINS); } /* insert waypoint count into header */ memcpy(&header_bytes[12], &s, 2); fwrite(&header_bytes, 1, 32, psp_file_out); - + waypt_disp_all(psp_disp); } diff --git a/gpsbabel/testo b/gpsbabel/testo index 30862b79b..9560d48a6 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -63,3 +63,11 @@ diff /tmp/ps.psp reference ${PNAME} -i mxf -f mxf.c -o mxf -F /tmp/mxf.mxf >/dev/null diff /tmp/mxf.mxf reference +# MXF (Maptech Exchange Format) file format +${PNAME} -i geo -f geocaching.loc -o mxf -F /tmp/mxf.mxf +diff /tmp/mxf.mxf reference + +# MXF (Maptech Exchange Format) file format +${PNAME} -i geo -f geocaching.loc -o mxf -F /tmp/mxf.mxf +diff /tmp/mxf.mxf reference + -- 2.30.2